/*
 * Copyright 2023, Haiku, Inc. All rights reserved.
 * Distributed under the terms of the MIT License.
 *
 * 龙芯3A6000 LS7A2000桥片 HPET定时器驱动
 */

#ifndef _LOONGSON_HPET_H
#define _LOONGSON_HPET_H

#include <KernelExport.h>
#include <SupportDefs.h>
#include "hpet_interface.h"

// LS7A2000 HPET寄存器基地址
#define LS7A_HPET_BASE_ADDRESS 0x10010000
#define LS7A_HPET_REGISTER_SIZE 0x1000

// HPET寄存器偏移量
#define LS7A_HPET_CAPABILITIES 0x00     // 能力和ID寄存器
#define LS7A_HPET_CONFIGURATION 0x10    // 配置寄存器
#define LS7A_HPET_INTERRUPT_STATUS 0x20 // 中断状态寄存器
#define LS7A_HPET_MAIN_COUNTER 0xF0     // 主计数器寄存器

// 定时器寄存器偏移量 (n = 0-31)
#define LS7A_HPET_TIMER_CONFIG(n) (0x100 + (n) * 0x20)     // 定时器配置寄存器
#define LS7A_HPET_TIMER_COMPARATOR(n) (0x108 + (n) * 0x20) // 定时器比较器寄存器
#define LS7A_HPET_TIMER_FSB_ROUTE(n) (0x110 + (n) * 0x20)  // 定时器FSB路由寄存器

// 配置寄存器位定义
#define LS7A_HPET_CFG_ENABLE (1 << 0) // 总体使能位
#define LS7A_HPET_CFG_LEGACY (1 << 1) // 传统替换路由使能

// 定时器配置寄存器位定义
#define LS7A_HPET_TN_INT_TYPE_LEVEL (1 << 1) // 电平触发中断
#define LS7A_HPET_TN_INT_ENB_CNF (1 << 2)    // 中断使能
#define LS7A_HPET_TN_TYPE_CNF (1 << 3)       // 周期性定时器使能
#define LS7A_HPET_TN_VAL_SET_CNF (1 << 6)    // 定时器值设置
#define LS7A_HPET_TN_32BIT_CNF (1 << 8)      // 32位模式使能

// 龙芯HPET特定配置
#define LS7A_HPET_TIMER_COUNT 4         // 龙芯HPET定时器数量
#define LS7A_HPET_CLOCK_PERIOD 10000000 // 时钟周期(飞秒)

// HPET定时器结构体
typedef struct
{
    area_id register_area; // 寄存器映射区域
    addr_t base_addr;      // 寄存器基地址
    uint32 timer_count;    // 定时器数量
    uint64 clock_period;   // 时钟周期(飞秒)
    bool is_64bit;         // 是否支持64位模式
    bool legacy_capable;   // 是否支持传统替换路由
} loongson_hpet;

// 函数声明
status_t loongson_hpet_init(void);
void loongson_hpet_uninit(void);

status_t loongson_hpet_set_enabled(bool enabled);
status_t loongson_hpet_set_legacy_mode(bool enabled);

status_t loongson_hpet_configure_timer(uint32 timer_index, uint32 config);
status_t loongson_hpet_set_timer(uint32 timer_index, uint64 relative_timeout, bool periodic);
status_t loongson_hpet_clear_timer(uint32 timer_index);

uint64 loongson_hpet_get_counter(void);
uint64 loongson_hpet_get_period(void);

#endif // _LOONGSON_HPET_H